package core;

import java.util.ArrayList;
import java.util.List;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import db.DbController;

public class Dictionary {
    private int dictID = -1;
    private int fromID = -1;
	private int toID = -1;
    private int delCount = 0;
    private String strURL = null; // path to the .dict file;.ifo file ; .idx file
	public boolean boolAvailable = false;// dicide if idr object has loaded the entries
	
    private IfoFile ifoFile = null;
    private IdxFile idxFile = null; // idr stores a list of entries
    private DictFile dictFile = null;
    
	public int getDictID() {
		return dictID;
	}
	public void setDictID(int dictID) {
		this.dictID = dictID;
	}
	public int getFromID() {
		return fromID;
	}
	public void setFromID(int fromID) {
		this.fromID = fromID;
	}
	public int getToID() {
		return toID;
	}
	public void setToID(int toID) {
		this.toID = toID;
	}
	public int getDelCount() {
		return delCount;
	}
	public void setDelCount(int delCount) {
			this.delCount = delCount;
	}
    public String getStrURL() {
		return strURL;
	}
	public void setStrURL(String strURL) {
		this.strURL = strURL;
	}
	public IfoFile getIfoFile() {
		return ifoFile;
	}
	public void setIfoFile(IfoFile ifoFile) {
		this.ifoFile = ifoFile;
	}
	public IdxFile getIdxFile() {
		return idxFile;
	}
	public void setIdxFile(IdxFile idxFile) {
		this.idxFile = idxFile;
	}
	public DictFile getDictFile() {
		return dictFile;
	}
	public void setDictFile(DictFile dictFile) {
		this.dictFile = dictFile;
	}
    // constructor
    public Dictionary(String url, int id, int fID, int tID, int del) {
        this.fromID = fID;
        this.toID = tID;
        this.dictID = id;
        this.delCount = del;
        this.strURL = url;
        this.ifoFile = new IfoFile(strURL + ".ifo");
        this.idxFile = new IdxFile(strURL + ".idx", ifoFile.getLongWordCount(), ifoFile.getLongIdxFileSize());
        this.dictFile = new DictFile(strURL + ".dict");
        if (this.ifoFile.boolIsLoaded && this.idxFile.boolIsLoaded) {
            this.boolAvailable = true;
        }
    }	
    public void reLoad() {
        this.boolAvailable = false;
        this.ifoFile.reload();
        this.idxFile.reload();
        if (this.ifoFile.boolIsLoaded && this.idxFile.boolIsLoaded) {
            this.boolAvailable = true;
        }
    }

    // lookup a word by its index
    public String lookupWord(int idx) {
        if (idx < 0 || idx >= idxFile.getLongWordCount()) {
            return "not found";
        }
        WordEntry tempEntry = idxFile.entryList.get((int) idx);
        return dictFile.getWordData(tempEntry.longOffset, tempEntry.longSize);
    }

    // lookup a word
    public String lookupWord(String word) {
        if (!boolAvailable) {
            return "the dictionary is not available";
        }
        int idx = (int) idxFile.findIndexForWord(word);
        return lookupWord(idx);
    }
    public List<Word> getNNearestWords(String word) {
        if (boolAvailable) {
            int idx = (int) idxFile.findIndexForWord(word);
            int nMax = DbController.getNumOfNearestWords() + idx;
            if (nMax > idxFile.getLongWordCount()) {
                nMax = (int) idxFile.getLongWordCount();
            }
            List<Word> wordList = new ArrayList<Word>();
            for (int i = idx; i < nMax; i++) {
                if (i != 0) {
                    Word tempWord = new Word();
                    tempWord.strWord = idxFile.entryList.get(i).strWord;
                    tempWord.index = i;
                    wordList.add(tempWord);
                }
            }
            return wordList;
        }
        return null;
    }

    // check if a word is in dictionary
    public boolean existWord(String word) {
        int wordIndex = (int) idxFile.findIndexForWord(word);
        if (wordIndex >= idxFile.getLongWordCount())
            return false;
        String lwrWord = word.toLowerCase();
        if (lwrWord.equals(idxFile.entryList.get(wordIndex).strLwrWord)) {
            return true;
        }
        return false;
    }

    public boolean addListOfWords(String pWord[], String pMean[]) {
        if (pWord.length != pMean.length || pWord.length == 0)
            return false;
        try {
            for (int i = 0; i < pWord.length; i++) {
                String strLwrWord = pWord[i].toLowerCase();
                int pos = (int) idxFile.findIndexForWord(strLwrWord);
                boolean bExist = false;
                if (pos < (int) idxFile.getLongWordCount()) {
                    if (strLwrWord.compareTo(((WordEntry) idxFile.entryList.get(pos)).strLwrWord) == 0) {
                        bExist = true;
                    }
                }
                long nextOffset = dictFile.addData(pMean[i]);
                if (nextOffset >= 0) {
                    if (bExist == false) {
                        idxFile.addEntry(pWord[i], nextOffset, pMean[i].length(), pos);
                    } else {
                        WordEntry tempEntry = idxFile.entryList.get(pos);
                        tempEntry.longOffset = nextOffset;
                        tempEntry.longSize = pMean[i].length();
                    }
                }
            }
            idxFile.write();
            ifoFile.setLongIdxFileSize(idxFile.getLongIdxFileSize());
            ifoFile.setLongWordCount(idxFile.getLongWordCount());
            ifoFile.write();
        } catch (Exception ex) {
            return false;
        }
        return true;
    }

    public boolean addWord(String word, String mean) {
        String[] pWord = new String[1];
        String[] pMean = new String[1];
        pWord[0] = word;
        pMean[0] = mean;
        return addListOfWords(pWord, pMean);
    }

    public boolean removeListOfWords(String pWord[]) {
        int delNum = 0;
        for (int i = 0; i < pWord.length; i++) {
            if (idxFile.removeEntry(pWord[i])) {
                delNum++;
            }
        }
        if (delNum > 0) {
            delCount += delNum;
            idxFile.write();
            ifoFile.setLongIdxFileSize(idxFile.getLongIdxFileSize());
            ifoFile.setLongWordCount(idxFile.getLongWordCount());
            ifoFile.write();
            return true;
        }
        return false;
    }

    public boolean removeWord(String word) {
        String[] pWord = new String[1];
        pWord[0] = word;
        return removeListOfWords(pWord);
    }

    public boolean reorganize() {
        String strTempURL = strURL + ".temp";
        boolAvailable = false;
        try {
            DataOutputStream dto = new DataOutputStream(new FileOutputStream(strTempURL));
            long offset = 0;
            for (int i = 0; i < idxFile.getLongWordCount(); i++) {
                DataInputStream dti = new DataInputStream(new FileInputStream(dictFile.getStrFileName()));
                WordEntry etr = (WordEntry) idxFile.entryList.get(i);
                byte[] bt = new byte[(int) etr.longSize];
                dti.skip(etr.longOffset);
                dti.read(bt);
                dti.close();
                dto.write(bt);
                dto.flush();
                etr.longOffset = offset;
                offset += bt.length;
                idxFile.entryList.set(i, etr);
            }
            dto.close();
            if (idxFile.write()) {
                (new File(dictFile.getStrFileName())).delete();
                new File(strTempURL).renameTo(new File(dictFile.getStrFileName()));
                boolAvailable = true;
            }
            delCount = 0;
        } catch (Exception ex) {
        }
        return boolAvailable;
    }

    public String parseToHTML(String strInput) {
        StringBuffer sbf = new StringBuffer();
        int count = 0;
        sbf.append("<div><pre><font>");
        for (int i = 0; i < strInput.length(); i++) {
            char c = strInput.charAt(i);
            if (c == '@' && count == 0) {
                sbf.append(c + "<font color='red'><b>");
                count++;
            } else if (c == '/' && count == 1) {
                sbf.append("</font></b><font color='blue'><i>" + c);
                count++;
            } else if (c == '/' && count == 2) {
                sbf.append(c + "</font></i>");
                count++;
            } else {
                sbf.append(c);
                if (c == '\n') {
                    if (count == 1) {
                        sbf.append("</font></b>");
                    } else if (count == 2) {
                        sbf.append("</font></i>");
                    }
                    count = 0;
                }
            }
        }
        sbf.append("</font></pre></div>");
        return sbf.toString();
    }
}
